package cn.yunyichina.openapi.proxy.utils;

import cn.yunyichina.openapi.proxy.config.HttpServerConfig;
import cn.yunyichina.openapi.proxy.entity.ApiClass;
import cn.yunyichina.openapi.proxy.entity.ProviderArgs;
import com.alibaba.dubbo.config.ApplicationConfig;
import com.alibaba.dubbo.config.ReferenceConfig;
import com.alibaba.dubbo.config.RegistryConfig;
import com.alibaba.dubbo.rpc.service.GenericService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 管理dubbo的消费者
 *
 * @author zhangkewen
 */
public class ServiceUtil {

    private static String localServiceName = "yyt-openapi-proxy";

    private static String intefacePrefix = "cn.yunyichina.provider.iface.service.";

    private static final String CUSTOMER_FILTER="TraceCFilter";

    /* 存储服务对应的信息 */
    private static Map<String, ProviderArgs> dicServices = new HashMap<>();

    public static Map<String, ProviderArgs> getDicServices() {
        return dicServices;
    }

    /* 日志 */
    private static final Logger logger = LoggerFactory.getLogger(ServiceUtil.class);

    /**
     * 初始化所有消费者,dubbo热启动
     *
     * @throws ClassNotFoundException
     */
    public static void init() throws ClassNotFoundException {
        // 当前应用配置
        ApplicationConfig application = new ApplicationConfig();
        application.setName(localServiceName);

        // 连接注册中心配置
        RegistryConfig registry = new RegistryConfig();
        String zooKeeperUrl=HttpServerConfig.getConfig().getZookeeperurl();
        registry.setAddress(zooKeeperUrl);
        registry.setProtocol("zookeeper");

        List<ApiClass> apiclasses = DBUtil.getApiClass();
        for (ApiClass apiclass : apiclasses) {
        	try{
        		 ProviderArgs args = new ProviderArgs();
        		 ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();   // 此实例很重，封装了与注册中心的连接以及与提供者的连接，请自行缓存，否则可能造成内存和连接泄漏
                 reference.setApplication(application);
                 reference.setRegistry(registry); // 多个注册中心可以用setRegistries()
                 reference.setInterface(intefacePrefix + apiclass.getApiClassDefine());
                 reference.setCheck(false);
                 reference.setGeneric(true);
                 reference.setFilter(CUSTOMER_FILTER);
                 reference.setTimeout(apiclass.getTimeout() * 1000);
                 if(StringUtils.isBlank(zooKeeperUrl)){
                	 if (!HttpServerUtil.isEmpty(apiclass.getServerUrl())) {
                         reference.setUrl(apiclass.getServerUrl() + "/" + intefacePrefix + apiclass.getApiClassDefine());
                     }else{
                    	 reference.setUrl("dubbo://127.0.0.1:"+apiclass.getPort()+"/" + intefacePrefix + apiclass.getApiClassDefine());
                     }
                 }
                 Object service = reference.get(); // 注意：此代理对象内部封装了所有通讯细节，对象较重，请缓存复用
                 args.setReference(reference);
                 args.setService(service);
                 dicServices.put(apiclass.getApiClassDefine(), args);
        	}catch(Exception ex){
        		logger.error("启动服务:"+apiclass.getApiClassDefine()+"失败",ex);
        	}
        }
    }

    /**
     * 关闭所有的消费者
     */
    public static void close() {
        for (Map.Entry<String, ProviderArgs> entry : dicServices.entrySet()) {
            try {
                logger.info("开始destroy:" + entry.getKey());
                entry.getValue().getReference().destroy();
                logger.info("完成destroy:" + entry.getKey());
            } catch (Exception e) {
                logger.error("destroy:" + entry.getKey() + "异常:" + e.getMessage());
            }
        }
    }
    
    /*重新加载某个子系统*/
    public static void reLoad(String apiClassDefine){
    	ApiClass apiclass=DBUtil.getApiClass(apiClassDefine);
    	if(apiclass==null)
    		return;
    	
    	ApplicationConfig application = new ApplicationConfig();
        application.setName(localServiceName);

        // 连接注册中心配置
        RegistryConfig registry = new RegistryConfig();
        String zooKeeperUrl=HttpServerConfig.getConfig().getZookeeperurl();
        registry.setAddress(zooKeeperUrl);
        registry.setProtocol("zookeeper");
    	
        try{
	    	ProviderArgs args = new ProviderArgs();
			ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();   // 此实例很重，封装了与注册中心的连接以及与提供者的连接，请自行缓存，否则可能造成内存和连接泄漏
	        reference.setApplication(application);
	        reference.setRegistry(registry); // 多个注册中心可以用setRegistries()
	        reference.setInterface(intefacePrefix + apiclass.getApiClassDefine());
	        reference.setCheck(false);
	        reference.setGeneric(true);
            reference.setFilter(CUSTOMER_FILTER);
	        reference.setTimeout(apiclass.getTimeout() * 1000);
	        if(StringUtils.isBlank(zooKeeperUrl)){
	        	 if (!HttpServerUtil.isEmpty(apiclass.getServerUrl())) {
	                 reference.setUrl(apiclass.getServerUrl() + "/" + intefacePrefix + apiclass.getApiClassDefine());
	             }else{
	            	 reference.setUrl("dubbo://127.0.0.1:"+apiclass.getPort()+"/" + intefacePrefix + apiclass.getApiClassDefine());
	             }
	         }
	        Object service = reference.get(); // 注意：此代理对象内部封装了所有通讯细节，对象较重，请缓存复用
	        args.setReference(reference);
	        args.setService(service);
	        dicServices.put(apiclass.getApiClassDefine(), args);
        }catch(Exception ex){
    		logger.error("启动服务:"+apiclass.getApiClassDefine()+"失败",ex);
    	}
    }

}
